• 默认情况下,bash shell会忽略收到的任何SIGQUIT(3)和SIGTERM(5)信号,但是bash shell会处理收到的SIGHUP(1)和SIGINT(2)信号,如果bash shell收到了SIGHUP信号,它就会退出,但在退出之前,它会将SIGHUP信号传给所有由该shell所启动的进程(包括正在运行的shell脚本)
  • Ctrl+C组合键会生成SIGINT信号,并将其发送给当前在shell中运行的所有进程,该信号会停止shell中当前运行的进程。
  • 可以在进程运行期间暂停进程,而无需终止它,Ctrl+Z组合键会生成一个SIGTSTP信号,停止shell中运行的任何进程,停止进程和终止进程不同:停止进程会让程序继续停留在内存中,并能从上次停止的位置继续运行。shell将shell中运行的每个进程称为作业,并为每个作业分配唯一的作业号,它会给第一个作业分配作业号1,第二个作业号2,可以使用ps -l命令察看已停止的作业,此时S列中进程的状态为T,表示命令要么被追踪,要么被停止了。
  • trap命令允许你来指定shell脚本要监看并从shell中拦截的Linux信号,如果脚本收到了trap命令中列出的信号,该信号不再由shell处理,而是交由本地处理: trap commands signals,commands表示想要shell执行的命令,signals表示待捕获的信号,可以用数值或Linux信号名来指定信号。
  • 要捕获shell脚本的退出,只要在trap命令后加上EXIT信号即可:trap “echo Goodbye…” EXIT
  • 在trap命令与希望恢复默认行为的信号列表之前加上两个破折号可以删除已设置好的捕获:trap – SIGINT
  • 在命令后加上&符号就可以让shell脚本以后台模式运行:./test.sh &,当执行了上面这条命令后,会输出类似于下面这条语句:[1] 3231,其中方括号中的数字是shell分配给后台进程的作业号,下一个数是Linux系统分配给进程的进程ID(PID)。
  • nohup命令运行了另外一个命令来阻断所有发送给该进程的SIGHUP信号,这会在退出终端会话时阻止进程退出:

    1
    nohup ./test.sh &

    由于nohup命令会解除终端和进程的关联,进程也就不再同STDOUT和STDERR联系在一起,为了保存该命令产生的输出,nohup命令会自动将STDOUT和STDERR的消息重定向到一个名为nohup.out文件中,需要注意的是当运行位于同一个目录中的多个命令时所有的输出都会被发送到同一个nohup.out文件中

  • 当使用Ctrl+Z命令将进程停止后,你可以使用kill命令停止该进程,要重启停止的进程需要向其发送一个SIGCONT信号
  • jobs命令可以查看分配给shell的作业,以及它们的作业号和作业中使用的命令,要想察看作业的PID,可以在jobs命令中加入-l选项,jobs输出中有加号和减号,带加号的作业被当作默认作业,在私用作业控制命令时,如果未在命令行指定任何作业号,该作业会被当成作业控制命令的操作对象,当前的默认作业完成处理后,带减号的作业成为下一个默认作业,任何时候都只有一个带加号的作业和一个带减号的作业,不管shell中有多少个正在运行的作业。
  • 要以后台模式重启一个作业,可用bg命令加上作业号,当然如果该作业是默认作业,只需要使用bg命令就可以将其以后台模式重启;要以前台模式重启作业,可用带作业号的fg命令。
  • 调度优先级是个整数值,从-20(最高优先级)到+19(最低优先级),默认情况下,bash shell以优先级0来启动所有进程。
  • nice命令允许你设置命令启动时的调度优先级,要让命令以更低的优先级运行,只要用nice的-n命令行来指定新的优先级级别:nice -n 10 ./test.sh > test.out &,可以用这条命令显示进程的谦让度值:ps -p 4973 -o pid,ppid,ni,cmd。当然,nice命令阻止普通系统用户来提高命令的优先级。

    nice命令的-n选项并不是必须的,只需要在破折号后面跟上优先级就行了:nice -10 ./test.sh > test.out

  • renice命令可以改变系统上已运行命令的优先级,它允许你指定运行进程的PID来改变它的优先级:

    1
    $ ./test.sh &
    1
    2
    3
    4
    5
    6
    7
    8
    9
    [1] 5055
    $ps -p 5055 -o pid,ppid,ni,cmd
    PID PPID NI CMD
    5055 4721 0 /bin/bash ./test.sh
    $renice -n 10 -p 5055
    5055: old priority 0, new priority 10
    ps -p 5055 -o pid,ppid,ni,cmd
    PID PPID NI CMD
    5055 4721 10 /bin/bash ./test.sh

    renice命令只能对属于你的进程执行renice,只能通过renice降低进程的优先级,root用户可以通过renice来任意调整进程的优先级。

  • at命令允许指定Linux系统何时运行脚本,at命令会将作业提交到队列中,指定shell何时运行该脚本,at的守护进程atd会以后台模式运行,检查作业队列来运行作业,大多数Linux发行版本在启动时运行此守护进程。

    atd守护进程会检查系统上的一个特殊目录(/var/spool/at)来获取用at命令提交的作业,默认情况下,atd守护进程会每60s检查一下这个目录,有作业时,atd守护进程会检查作业设置运行的时间,如果时间跟当前时间匹配,atd守护进程会运行此作业

    at命令的格式如下:at [-f filename] time,默认情况下at命令会将STDIN的输入放到队列中,你可以用-f参数来指定用于读取命令(脚本文件)的文件名,time参数指定了Linux系统何时运行该作业,如果指定的时间已经错过,at命令会在第二天的那个时间运行指定的作业。

    at命令能识别多种不同的时间格式:

    • 标准的小时和分钟格式: 10:15
    • AM/PM指示符:10:15 PM
    • 特定可命名时间,比如now、noon、midnight、teatime(4PM)

    除了指定运行作业的时间,也可以通过不同的日期格式指定特定的日期:

    • 标准日期格式:MMDDYY、MM/DD/YY、DD.MM.YY
    • 文本日期:Jul 4、Dec 25,加不加年份均可

    你也可以指定时间增量:

    • 当前时间+25min
    • 明天10:15 PM
    • 10:15+7天

    在使用at命令时,该作业会被提交到作业队列,针对不同优先级,存在26种不同的作业队列,通过用小写字母a~z和大写字母A~Z来指代,作业队列的字母排序越高,作业运行的优先级越低(更高的nice值),默认情况下,at的作业会被提交到a作业队列,如果想以更高优先级运行作业,可以用-q参数指定不同的队列字母。

    at命令指定的作业在运行时,显示器并不会关联到该作业,Linux系统会将提交该作业的用户的电子邮件地址作业STDOUT和STDERR,任何法道STDOUT和STDERR的输出会通过邮件系统发送给该用户。

    at命令会显示分配给作业的作业号以及为作业安排的运行时间。

    在使用at命令时,最好在脚本中对STDOUT和STDERR进行重定向。

  • atq命令可以列出系统中有哪些作业在等待,作业列表中列出了作业号、系统运行该作业的日期和时间以及所在的作业队列
  • 一旦知道了哪些作业在作业队列中等待,就能用atrm命令来删除等待中的作业,指明想要删除的作业号即可
  • Linux使用cron程序来安排要定期指定的作业,cron程序会在后台运行并检查一个特殊的表(称为cron时间表),以获知已安排执行的作业。

    cron时间表采用一种特别的格式来指定作业何时运行:min hour dayofmonth month dayofweek command,cron时间表允许你用特定值、取值范围或者通配符来指定条目,例如想在每天的10:15运行一个命令:

    15 10 * command

    cron程序会用提交作业的用户账户运行该脚本,因此你必须有访问该命令和命令中指定的输出文件的权限

  • 可以使用crontab命令来处理cron时间表,要列出已有的cron时间表,可以用-l选项,默认情况下,用户的cron时间表文件不存在,要为cron时间表添加条目,可以用-e选项,在添加条目时crontab命令会启用一个文本编辑器。

    如果你创建的脚本对精确的执行时间要求不高,用预配置的cron脚本目录会更方便,有4个基本目录:hourly、daily、monthly、weekly:

    1
    2
    3
    4
    5
    6
    7
    8
    $ ls /etc/cron.*ly
    /etc/cron.daily:
    cups makewhatis.cron prelink tmpwatch
    /etc/cron.hourly:
    0anacron
    /etc/cron.monthly:
    readahead-monthly.cron
    /etc/cron.weekly:

    因此,如果脚本需要每天运行一次,只要将脚本复制到daily目录,cron就会每天执行它